class AILogic {



	/**
	 * 手牌评分,用来AI根据自己手牌来叫分
	 */
	public static judgeScore(player) {
		var score = 0;
		// 一个炸弹加6分
		score += player.bomb.length * 6;
		// 王炸8分
		if (player.kingBomb.length > 0) {
			score += 8;
		} else {
			if (player.cardList[0].val === 17) {
				// 大王加4分
				score += 4;
			} else if (player.cardList[0].val === 16) {
				score += 3;
			}
		}
		for (var i: number = 0; i < player.cardList.length; i++) {
			if (player.cardList[i].val === 15) {
				// 2加  2分
				score += 2;
			}
		}
		console.log(player.name + '手牌评分:' + score);
		// 根据得分来判断叫几分
		if (score >= 7) {
			return 3;
		} else if (score >= 5) {
			return 2;
		} else if (score >= 3) {
			return 1
		} else {
			// 4为不叫
			return 4;
		}



	}
	/**
	 * 牌型分析
	*/
	public static analyse(player: Player) {
		// // 拷贝一份牌来分析
		// var target = player.cardList.slice(0);
		// // 判定王炸
		// if (GameRule.isKingBomb(target.slice(0, 2))) {
		// 	// 把王炸保存并删去
		// 	player.kingBomb.push(new AICardType(17, target.splice(0.2)));
		// }
		// // 判定炸弹
		// var c = GameRule.valCount(target);
		// for (var i: number = 0; i < c.length; i++) {
		// 	if (c[i].count === 4) {
		// 		var list = [];
		// 		// 把炸弹保存并删除
		// 		AILogic.moveItem(target, list, c[i].val);
		// 		player.bomb.push(new AICardType(list[0].val, list));
		// 	}
		// }
		// // 此刻的牌组已经删除王炸和炸弹(防止AI过于聪明,不让炸弹参与其他牌型,例如炸弹拆成三根和单张)
		// var targetWodt = target.slice(0);
		// // 判定三根
		// AILogic.judgeThree(targetWodt, player);
		// // 判定三顺(飞机不带牌)
		// AILogic.judgePlane(targetWodt, player);
		// // 判定顺子(五连)
		// var targetP = target.slice(0);
		// AILogic.judgeProgression(targetP, player);
		// // 判断连对
		// AILogic.judgeProgressionPairs(targetP, player);
		// // 除去顺子,炸弹,三根后判断对子,单牌
		// var c = GameRule.valCount(targetP);
		// for (var i: number = 0; i < c.length; i++) {
		// 	if (c[i].count === 1) {
		// 		// 单牌
		// 		for (var j: number = 0; j < targetP.length; j++) {
		// 			if (targetP[j].val === c[i].val) {
		// 				player.one.push(new AICardType(c[i].val, targetP.splice(j, 1)));
		// 			}
		// 		}
		// 	} else if (c[i].count === 2) {
		// 		for (var j: number = 0; j < targetP.length; j++) {
		// 			if (targetP[j].val === c[i].val) {
		// 				player.pairs.push(new AICardType(c[i].val, targetP.splice(j, 2)));
		// 			}
		// 		}
		// 	}
		// }



		// 使用新逻辑
		// 拷贝一份牌来分析
		var target = player.cardList.slice(0);
		// 每次分析都要清空原来的牌组

		// 定义牌型
		// 单张
		player.one = [];
		// 对子
		player.pairs = [];
		// 王炸
		player.kingBomb = [];
		// 炸弹
		player.bomb = [];
		// 三张
		player.three = [];
		// 飞机
		player.plane = [];
		// 顺子
		player.progression = [];
		// 三带2
		player.progressionPairs = [];


		// 找出来王炸
		if (GameRule.isKingBomb(target.slice(0, 2))) {
			// 把王炸保存并删去
			player.kingBomb.push(new AICardType(17, target.splice(0, 2)));
		}
		// 找出来炸弹
		var c = GameRule.valCount(target);
		for (var i: number = 0; i < c.length; i++) {
			if (c[i].count === 4) {
				var list = [];
				// 把炸弹保存并删除
				AILogic.moveItem(target, list, c[i].val);
				player.bomb.push(new AICardType(list[0].val, list));
			}
		}
		// 找出来三根
		AILogic.judgeThree(target, player);
		// 在三根的基础上,找出来飞机
		AILogic.judgePlane(target, player);
		// 找出来五连顺
		AILogic.judgeProgression(target, player);
		// 找出来对子
		var c = GameRule.valCount(target);
		for (var i: number = 0; i < c.length; i++) {
			if (c[i].count === 2) {
				var list = [];
				AILogic.moveItem(target, list, c[i].val);
				player.pairs.push(new AICardType(list[0].val, list));
			}
		}
		// 找出来所有的连对
		AILogic.judgeProgressionPairs(target, player);
		// 剩下的就是单牌
		// 除去顺子,炸弹,三根后判断对子,单牌
		var c = GameRule.valCount(target);
		for (var i: number = 0; i < c.length; i++) {
			if (c[i].count === 1) {
				// 单牌
				for (var j: number = 0; j < target.length; j++) {
					if (target[j].val === c[i].val) {
						player.one.push(new AICardType(c[i].val, target.splice(j, 1)));
					}
				}
			}
			// else if (c[i].count === 2) {
			// 	for (var j: number = 0; j < target.length; j++) {
			// 		if (target[j].val === c[i].val) {
			// 			player.pairs.push(new AICardType(c[i].val, target.splice(j, 2)));
			// 		}
			// 	}
			// }
		}
	}


	/**
	 * 将src中对应值的牌数据移动到dest中
	*/
	public static moveItem(src, dest, v) {
		for (var i = src.length - 1; i >= 0; i--) {
			if (src[i].val === v) {
				dest.push(src.splice(i, 1)[0]);
			}
		}
	}


	/**
	 * 判断给定牌中的三根
	*/
	public static judgeThree(cards, player) {
		var c = GameRule.valCount(cards);
		for (var i: number = 0; i < c.length; i++) {
			if (c[i].count === 3) {
				var list = [];
				AILogic.moveItem(cards, list, c[i].val);
				player.three.push(new AICardType(list[0].val, list));
			}
		}
	}
	/**
	 * 判断给定牌中的飞机
	*/
	public static judgePlane(cards, player) {
		if (player.three.length > 1) {
			// 判断是否有三根..有三根才能有飞机的可能
			// 声明数组,用来存放可能是飞机的牌型对象
			var prolist = [];
			for (var i: number = 0; i < player.three.length; i++) {
				if (player.three[i].val >= 15) {
					// 三根大于2,过滤掉
					continue;
				}
				if (prolist.length == 0) {
					// 往飞机对象数组里添加一个三根
					prolist.push({ 'obj': player.three[i], 'fromIndex': i });
					continue;
				}
				if (prolist[prolist.length - 1].val - 1 == player.three[i].val) {
					// 飞机对象数组最后一个与下一个三根相连的话,则加入飞机对象数组
					prolist.push({ 'obj': player.three[i], 'fromIndex': i });
				} else {
					// 下一个三根跟上一个三根不连续
					if (prolist.length > 1) {
						// 飞机对象数组里有两个以上的三根,已经形成飞机
						var planeCards = [];
						for (var j: number = 0; j < prolist.length; j++) {
							// 把飞机对象数组格式化,添加到玩家的飞机牌组里去
							planeCards = planeCards.concat(prolist[j].obj.cardList);
						}
						player.plane.push(new AICardType(prolist[0].obj.val, planeCards));
						for (var k = prolist.length - 1; k >= 0; k--) {
							// 删除已经被取走的牌
							player.three.splice(prolist[k].fromIndex, 1);
						}
					}
					// 飞机对象数组里只有一个三根,下一个三根又不连续,则舍弃之前的三根,加入现在的三根.
					prolist = [];
					prolist.push({ 'obj': player.three[i], 'fromIndex': i });
				}
			}
			// 三根数组里面,都是相连的三根
			if (prolist.length > 1) {
				var planeCards = [];
				for (var i: number = 0; i < prolist.length; i++) {
					planeCards = planeCards.concat(prolist[i].obj.cardList);
				}
				player.plane.push(new AICardType(prolist[0].obj.val, planeCards));
				for (var i: number = prolist.length - 1; i >= 0; i++) {
					player.three.splice(prolist[i].fromIndex, 1);
				}
			}
		}
	}
	/**
	 * 判断给定牌中的顺子(五连)
	*/
	public static judgeProgression(cards, player) {
		if (cards.length >= 5) {
			var prolist = [];
			for (var i: number = 0; i < cards.length; i++) {
				if (cards[i].val >= 15) {
					// 顺子过滤2
					continue;
				}
				if (prolist.length == 0) {
					prolist.push({ 'obj': cards[i], 'fromIndex': i });
					continue;
				}
				if (prolist[prolist.length - 1].obj.val - 1 == cards[i].val) {
					// 相连续的牌
					prolist.push({ 'obj': cards[i], 'fromIndex': i });
					if (prolist.length === 5) {
						// 五连的目标达成
						break;
					}
				} else if (prolist[prolist.length - 1].obj.val === cards[i].val) {
					// 相等的牌.继续
					continue;
				} else {
					// 下一张牌开始不连续了
					if (prolist.length >= 5) {
						// 再次判断,是否已经组成了顺子
						break;
					} else {
						// 重新计算
						prolist = [];
						prolist.push({ 'obj': cards[i], 'fromIndex': i });
					}
				}
			}
			if (prolist.length === 5) {
				// 有顺子,保存
				var progression = [];
				for (var i: number = 0; i < prolist.length; i++) {
					progression.push(prolist[i].obj);
				}
				player.progression.push(new AICardType(prolist[0].obj.val, progression))
				for (var i: number = prolist.length - 1; i >= 0; i--) {
					cards.splice(prolist[i].fromIndex, 1);
				}
				// 再来一次,判断还有其他顺子没有
				AILogic.judgeProgression(cards, player);
			} else {
				// 将顺子与剩下的牌进行拼接,组成更大的顺子,6连顺,7连顺...
				AILogic.joinProgression(cards, player);
			}
		}
	}
	/**
	 * 将五连顺子继续扩大
	*/
	public static joinProgression(cards, player) {
		for (var i: number = 0; i < player.progression.length; i++) {
			// 拼接其他散牌
			for (var j: number = 0; j < cards.length; j++) {
				if (player.progression[i].val != 14 && player.progression[i].val === cards[j].val - 1) {
					// 散牌能拼接在五顺的前面
					player.progress[i].cardList.unshift(cards.splice(j, 1)[0]);
				} else if (cards[j].val === player.progression[i].val - player.progression[i].cardList.length) {
					// 散牌能拼接在五顺的后面
					player.progression[i].cardList.push(cards.splice(j, 1, )[0]);
				}
			}
		}
		var temp = player.progression.slice(0);
		for (var i: number = 0; i < temp.length; i++) {
			if (i < temp.length - 1 && temp[i].val - temp[i].cardList.length === temp[i + 1].val) {
				// 连个顺子其实是可以连在一起的
				player.progression[i].cardList = player.progression[i].cardList.concat(player.progression[i + 1].cardList);
				player.progression.splice(++i, 1);
			}
		}
	}
	/**
	 * 判断给定牌中的连对
	*/
	public static judgeProgressionPairs(cards, player) {
		// if (cards.length >= 6) {
		// 	var prolist = [];
		// 	var c = GameRule.valCount(cards);
		// 	for (var i: number = 0; i < c.length; i++) {
		// 		if (c[i].val >= 15) {
		// 			// 连对过滤2
		// 			continue;
		// 		}
		// 		if (prolist.length == 0 && c[i].count >= 2) {
		// 			prolist.push(c[i].val);
		// 			continue;
		// 		}
		// 		if (prolist[prolist.length - 1] - 1 === c[i].val && c[i].count >= 2) {
		// 			// 满足下一个对是连对
		// 			prolist.push(c[i].val);
		// 		} else {
		// 			if (prolist.length >= 3) {
		// 				// 下一对中断了,但之前已经形成连对了
		// 				break;
		// 			} else {
		// 				// 重新计算
		// 				prolist = [];
		// 				if (c[i].count >= 2) {
		// 					prolist.push(c[i].val);
		// 				}
		// 			}
		// 		}
		// 	}
		// 	if (prolist.length >= 3) {
		// 		// 有顺子
		// 		var progressionPairs = [];
		// 		for (var i: number = 0; i < prolist.length; i++) {
		// 			for (var j = 0; j < cards.length; j++) {
		// 				if (cards[j].val === prolist[i]) {
		// 					progressionPairs = progressionPairs.concat(cards.splice(j, 2));
		// 					break;
		// 				}
		// 			}
		// 		}
		// 		// 排序
		// 		progressionPairs.sort(Data.bTos);
		// 		player.progressionPairs.push(new AICardType(prolist[0], progressionPairs));
		// 		// 再次查询
		// 		AILogic.judgeProgressionPairs(cards, player);

		// 	}

		// }



		if (player.pairs.length >= 3) {
			// 判断是否有连对..有三对才能有飞机的可能
			// 声明数组,用来存放可能是飞机的牌型对象
			var prolist = [];
			for (var i: number = 0; i < player.pairs.length; i++) {
				if (player.pairs[i].val >= 15) {
					// 对子大于2,过滤掉
					continue;
				}
				if (prolist.length == 0) {
					// 往飞机对象数组里添加一个对子
					prolist.push({ 'obj': player.pairs[i], 'fromIndex': i });
					continue;
				}
				if (prolist[prolist.length - 1].val - 1 == player.pairs[i].val) {
					// 飞机对象数组最后一个与下一个对子相连的话,则加入飞机对象数组
					prolist.push({ 'obj': player.pairs[i], 'fromIndex': i });
				} else {
					// 下一个对子跟上一个对子不连续
					if (prolist.length > 2) {
						// 飞机对象数组里有两个以上的对子,已经形成飞机
						var planeCards = [];
						for (var j: number = 0; j < prolist.length; j++) {
							// 把飞机对象数组格式化,添加到玩家的飞机牌组里去
							planeCards = planeCards.concat(prolist[j].obj.cardList);
						}
						player.plane.push(new AICardType(prolist[0].obj.val, planeCards));
						for (var k = prolist.length - 1; k >= 0; k--) {
							// 删除已经被取走的牌
							player.pairs.splice(prolist[k].fromIndex, 1);
						}
					}
					// 飞机对象数组里只有一个对子,下一个对子又不连续,则舍弃之前的对子,加入现在的对子.
					prolist = [];
					prolist.push({ 'obj': player.pairs[i], 'fromIndex': i });
				}
			}
			// 对子数组里面,都是相连的对子
			if (prolist.length > 2) {
				var planeCards = [];
				for (var i: number = 0; i < prolist.length; i++) {
					planeCards = planeCards.concat(prolist[i].obj.cardList);
				}
				player.plane.push(new AICardType(prolist[0].obj.val, planeCards));
				for (var i: number = prolist.length - 1; i >= 0; i++) {
					player.pairs.splice(prolist[i].fromIndex, 1);
				}
			}
		}


	}

	/**
	 * AI出牌,默认出包含最小的牌	
	*/
	public static play(player: Player, landlordCardsCnt) {
		for (var i: number = player.cardList.length - 1; i >= 0; i--) {
			// 找到最小的牌,并判断它的牌型
			var r = AILogic.cardsWithMin(i, player);
			console.log(r);
			console.log(player);
			if (r.cardKind === GameRule.ONE) {
				if (player.plane.length > 0) {
					// 有飞机
					var plane = AILogic.minCards(player.plane, GameRule.PLANE);
					var len = plane.cardList.length / 3;
					var currOneVal = 2;
					for (var i: number = 0; i < len; i++) {
						// 拿一张单牌
						var one = AILogic.minOne(currOneVal, plane.val, player);
						plane.cardList.push(one);
						currOneVal = one.val;
					}
					// 飞机带单根
					return AILogic.setCardKind(plane, GameRule.PLANE_WITH_ONE);
				} else if (player.three.length > 0) {
					// 三带一
					var three = AILogic.minCards(player.three, GameRule.THREE);
					var len = three.cardList.length / 3;
					var currOneVal = 2;
					var one = AILogic.minOne(currOneVal, three.val, player);
					if (one) {
						three.cardList.push(one);
					}
					if (three.val < 14) {
						return AILogic.setCardKind(three, GameRule.THREE_WITH_ONE);
					}
				}
				if (player.isLandlord) {
					// 坐庄打法
					if (player.nextPlayer.cardList.length <= 2 || player.nextPlayer.nextPlayer.cardList.length <= 2) {
						return AILogic.playOneAtTheEnd(player, landlordCardsCnt);
					} else {
						return AILogic.minCards(player.one, GameRule.ONE);
					}
				} else {
					// 偏家打法
					if (landlordCardsCnt <= 2) {
						// 地主还有两张牌
						return AILogic.playOneAtTheEnd(player, landlordCardsCnt)
					} else {
						return AILogic.minCards(player.one, GameRule.ONE);
					}
				}
			} else if (r.cardKind === GameRule.THREE) {
				var three = AILogic.minCards(player.three, GameRule.THREE);
				var len = three.cardList.length / 3;
				var currOneVal = 2;
				if (player.one.length > 0) {
					// 三带一
					var one = AILogic.minOne(currOneVal, three.val, player);
					three.cardList.push(one);
					return AILogic.setCardKind(three, GameRule.THREE_WITH_ONE);
				} else if (player.pairs.length > 0) {
					var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
					three.cardList = three.cardList.concat(pairs.cardList);
					return AILogic.setCardKind(three, GameRule.THREE_WITH_PAIRS);
				} else {
					return AILogic.setCardKind(three, GameRule.THREE);
				}
			} else if (r.cardKind === GameRule.PLANE) {
				var plane = AILogic.minCards(player.plane, GameRule.PLANE);
				var len = plane.cardList.length / 3;
				if (player.one.length > len && player.pairs.length > len) {
					// 飞机带单还是带对
					if (player.one.length > len) {
						// 先带单
						var currOneVal = 2;
						for (var i: number = 0; i < len; i++) {
							var one = AILogic.minOne(currOneVal, plane.val, player);
							if (one) {

								plane.cardList.push(one);
							}

							currOneVal = one.val;
						}
						return AILogic.setCardKind(plane, GameRule.PLANE_WITH_ONE);
					} else {
						var currOneVal = 2;
						for (var i: number = 0; i < len; i++) {
							var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
							currOneVal = pairs.val;
						}
						return AILogic.setCardKind(plane, GameRule.PLANE_WITH_PAIRS);
					}
				} else if (player.pairs.length > len) {
					var currOneVal = 2;
					for (var i: number = 0; i < len; i++) {
						var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
						currOneVal = pairs.val;
					}
					return AILogic.setCardKind(plane, GameRule.PLANE_WITH_PAIRS);
				} else if (player.one.length > len) {
					var currOneVal = 2;
					for (var i: number = 0; i < len; i++) {
						var one = AILogic.minOne(currOneVal, plane.val, player);
						plane.cardList.push(one);
						currOneVal = one.val;
					}
					return AILogic.setCardKind(plane, GameRule.PLANE_WITH_ONE);
				} else {
					return AILogic.setCardKind(plane, GameRule.PLANE);
				}
			} else if (r.cardKind === GameRule.BOMB && AILogic.times(player) === 1) {
				return r;
			} else if (r.cardKind === GameRule.BOMB && AILogic.times(player) != 1) {
				continue;
			} else {
				return r;
			}
		}
	}

	/**
	 * 找出最小的牌
	*/
	public static cardsWithMin(index, player: Player) {
		var minCard = player.cardList[index];
		// 在单根里找
		for (var i: number = 0; i < player.one.length; i++) {
			if (player.one[i].val === minCard.val) {
				return AILogic.minCards(player.one, GameRule.ONE);
			}
		}
		// 在对子里找
		for (var i: number = 0; i < player.pairs.length; i++) {
			if (player.pairs[i].val === minCard.val) {
				return AILogic.minCards(player.pairs, GameRule.PAIRS);
			}
		}
		// 在三根里找
		for (var i: number = 0; i < player.three.length; i++) {
			if (player.three[i].val === minCard.val) {
				return AILogic.minCards(player.three, GameRule.THREE);
			}
		}
		// 在炸弹里找
		for (var i: number = 0; i < player.bomb.length; i++) {
			if (player.bomb[i].val === minCard.val) {
				return AILogic.minCards(player.bomb, GameRule.BOMB);
			}
		}
		// 在飞机里找
		for (var i: number = 0; i < player.plane.length; i++) {
			for (var j: number = 0; j < player.plane[i].cardList.length; j++) {
				if (player.plane[i].cardList[j].val === minCard.val && player.plane[i].cardList[j].type === minCard.type) {
					return AILogic.minCards(player.plane, GameRule.PLANE);
				}
			}
		}
		// 在顺子里找
		for (var i: number = 0; i < player.progression.length; i++) {
			for (var j: number = 0; j < player.progression[i].cardList.length; j++) {
				if (player.progression[i].cardList[j].val === minCard.val && player.progression[i].cardList[j].type === minCard.type) {
					return AILogic.minCards(player.progression, GameRule.PROGRESSION);
				}
			}
		}
		// 在连对里找
		for (var i: number = 0; i < player.progressionPairs.length; i++) {
			for (var j: number = 0; j < player.progressionPairs[i].cardList.length; j++) {
				if (player.progressionPairs[i].cardList[j].val === minCard.val && player.progressionPairs[i].cardList[j].type === minCard.type) {
					return AILogic.minCards(player.progressionPairs, GameRule.PROGRESSION_PAIRS);
				}
			}
		}
		if (player.kingBomb.length > 0) {
			return AILogic.minCards(player.kingBomb, GameRule.KING_BOMB);
		}


		return AILogic.minCards(player.one, GameRule.ONE);
	}
	/**
	 * 获取list中大过v的最小的元素
	*/
	public static minCards(list: Array<any>, kind, v = 2) {
		if (list.length > 0) {
			for (var i: number = list.length - 1; i >= 0; i--) {
				// 从小到大开始判断
				if (v < list[i].val) {
					return AILogic.setCardKind(list[i], kind);
				}
			}
		}
		return null;
	}
	/**
	 * 设置返回牌的类型
	*/
	public static setCardKind(obj, kind) {
		obj.cardKind = kind;
		obj.size = obj.cardList.length;
		return obj;
	}
	/**
	 * 从对子或者单牌这获取一张牌
	*/
	public static minOne(v, notEq, player: Player) {
		var one = AILogic.minCards(player.one, GameRule.ONE, v);
		var oneFromPairs = AILogic.offPairs(v, notEq, player);

		if (!one) {
			// 没有单张,找对
			if (oneFromPairs) {
				AILogic.deleteOne(oneFromPairs, player);
				return oneFromPairs;
			} else {
				return null;
			}
		} else {
			if (one.val > 14) {
				// 保留2和大小王
				if (oneFromPairs) {
					AILogic.deleteOne(oneFromPairs, player);
				} else {
					return null;
				}

			} else {
				return one.cardList[0];
			}
		}
		return null;
	}
	/**
	 * 拆对.v要大过的值,notEq不能等于值
	*/
	public static offPairs(v, notEq, player: Player) {
		var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, v);
		if (pairs) {
			while (true) {
				if (pairs.cardList[0].val === notEq) {
					pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, pairs.cardList[0].val);
				} else {
					break;
				}
			}
		}
		return pairs ? pairs.cardList[0] : null;

	}
	/**
	 * 删掉一张牌并重新分析
	*/
	public static deleteOne(card, player: Player) {
		for (var i: number = 0; i < player.cardList.length; i++) {
			if (player.cardList[i].val === card.val && player.cardList[i].type === card.type) {
				player.cardList.splice(i, 1)
			}
		}
		AILogic.analyse(player);
	}
	/**
	 * 出牌将单根放最后出牌	
	*/
	public static playOneAtTheEnd(player: Player, landlordCardsCnt) {
		if (player.progression.length > 0) {
			// 先出顺子
			return AILogic.minCards(player.progression, GameRule.PROGRESSION);
		} else if (player.plane.length > 0) {
			// 有飞机
			var plane = AILogic.minCards(player.plane, GameRule.PLANE);
			var len = plane.cardList / 3;
			if (player.one.length > len && player.pairs.length > len) {
				// 如果单根多就飞机带单,否则,飞机带对
				if (player.one.length >= player.pairs.length) {
					var currOneVal = 2;
					for (var i: number = 0; i < len; i++) {
						var one = AILogic.minOne(currOneVal, plane.val, player);
						plane.cardList.push(one);
						currOneVal = one.val;
					}
					return AILogic.setCardKind(plane, GameRule.PLANE_WITH_ONE);
				} else {
					var currOneVal = 2;
					for (var i: number = 0; i < len; i++) {
						var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
						plane.cardList = plane.cardList.concat(pairs.cardList);
						currOneVal = pairs.val;
					}
					return AILogic.setCardKind(plane, GameRule.PLANE_WITH_PAIRS);
				}
			} else if (player.pairs.length > len) {
				var currOneVal = 2;
				for (var i: number = 0; i < len; i++) {
					var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
					plane.cardList = plane.cardList.concat(pairs.cardList);
					currOneVal = pairs.val;
				}
				return AILogic.setCardKind(plane, GameRule.PLANE_WITH_PAIRS);
			} else if (player.one.length > len) {
				var currOneVal = 2;
				for (var i: number = 0; i < len; i++) {
					var one = AILogic.minOne(currOneVal, plane.val, player);
					plane.cardList.push(one);
					currOneVal = one.val;
				}
				return AILogic.setCardKind(plane, GameRule.PLANE_WITH_ONE);
			} else {
				// 只出飞机
				return AILogic.setCardKind(plane, GameRule.PLANE);
			}
		} else if (player.progressionPairs.length > 0) {
			// 有连对
			return AILogic.minCards(player.progressionPairs, GameRule.PROGRESSION_PAIRS);
		} else if (player.three.length > 0) {
			// 有三根,先出三带一,之后三代二,最后只出三根
			var three = AILogic.minCards(player.three, GameRule.THREE);
			var len = three.cardList.length / 3;
			if (player.one.length > 0) {
				var currOneVal = 2;
				var one = AILogic.minOne(currOneVal, three.val, player);
				three.cardList.push(one);
				return AILogic.setCardKind(three, GameRule.THREE_WITH_ONE);
			} else if (player.pairs.length > 0) {
				var currOneVal = 2;
				var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
				three.cardList = three.cardList.concat(pairs.cardList);
				return AILogic.setCardKind(three, GameRule.THREE_WITH_PAIRS);
			} else {
				return AILogic.setCardKind(three, GameRule.THREE);
			}
		} else if (player.pairs.length > 0) {
			if (player.isLandlord && (player.nextPlayer.cardList.length === 2 || player.nextPlayer.nextPlayer.cardList.length === 2) || (!player.isLandlord && landlordCardsCnt === 2)) {
				// 如果自己是地主,并且两个农民就剩两张牌了,再或者地主只剩两张牌了...选大牌顶
				return AILogic.maxCards(player.pairs, GameRule.PAIRS);
			} else {
				return AILogic.minCards(player.pairs, GameRule.PAIRS);
			}
		} else if (player.one.length > 0) {
			// 出单牌
			if (player.isLandlord && (player.nextPlayer.cardList.length <= 2 || player.nextPlayer.nextPlayer.cardList.length <= 2) || (!player.isLandlord && landlordCardsCnt <= 2)) {
				return AILogic.maxCards(player.one, GameRule.ONE);
			} else {
				return AILogic.minCards(player.one, GameRule.ONE);
			}
		} else {
			var one = null;
			if (player.isLandlord && (player.nextPlayer.cardList.length <= 2 || player.nextPlayer.nextPlayer.cardList.length <= 2) || (!player.isLandlord && landlordCardsCnt <= 2)) {
				one = player.cardList.slice(player.cardList.length - 1, player.cardList.length);
			} else {
				one = player.cardList.slice(0, 1);
			}
			return {
				size: 1,
				cardKind: GameRule.ONE,
				cardList: one,
				val: one[0].val
			}
		}
	}
	/**
	 * 获取list对应牌型中最大list,kind牌型,v要大过的值	
	*/
	public static maxCards(list, kind, v = null) {
		var max = null;
		if (list.length > 0) {
			for (var i: number = 0; i < list.length; i++) {
				if ((max && list[i].val > max.val) || !max) {
					max = list[i];
				}
			}
			return v ? (max.val > v ? AILogic.setCardKind(max, kind) : null) : AILogic.setCardKind(max, kind);
		}
		return null;
	}
	/**
	 * 手数,手牌需要打出几次才能打完
	*/
	public static times(player: Player) {
		var t = player.kingBomb.length +
			player.bomb.length +
			player.progression.length +
			player.progressionPairs.length +
			player.one.length +
			player.pairs.length;
		var threeCount = player.three.length;
		if (player.plane.length > 0) {
			for (var i: number = 0; i < player.plane.length; i++) {
				threeCount += player.plane[i].cardList.length / 3;
			}
		}
		if (threeCount - (player.one.length + player.pairs.length) > 0) {
			t += threeCount - (player.one.length + player.pairs.length);
		}
		return t;
	}
	/**
	 * 跟牌,AI根据上家牌出牌
	 * winc 当前牌面最大牌
	 * isWinnerIsLandlord 当前最大是否是地主
	 * winnerCardCount 当前最大牌那家剩余手牌数
	*/
	public static follow(player: Player, winc, isWinnerIsLandlord, winnerCardCount) {
		var result = AILogic.judgeCardKind(player, winc, isWinnerIsLandlord, winnerCardCount);
		if (result) {
			return result;
		} else if (winc.cardKind != GameRule.BOMB && winc.cardKind != GameRule && (player.bomb.length > 0 || player.kingBomb.length > 0)) {
			if ((isWinnerIsLandlord && winnerCardCount < 5) || (player.isLandlord && (player.cardList.length < 5 || (player.nextPlayer.cardList.length < 5 || player.nextPlayer.nextPlayer.cardList.length < 6))) || AILogic.times(player) <= 2) {
				// 自己只有两手牌,或只有炸弹  必出炸弹
				if (player.bomb.length > 0) {
					return AILogic.minCards(player.bomb, GameRule.BOMB);
				} else {
					return AILogic.setCardKind(player.kingBomb[0], GameRule.KING_BOMB);
				}

			}

		} else {
			return null;
		}

	}
	/**
	 * 跟牌判断牌型
	 * winc 当前牌面最大牌
	 * isWinnerIsLandlord 当前最大是否是地主
	 * winnerCardCount 当前最大牌那家剩余手牌数
	*/
	public static judgeCardKind(player: Player, winc, isWinnerIsLandlord, winnerCardCount) {
		switch (winc.cardKind) {
			case GameRule.ONE:
				// 单牌
				var one = AILogic.matchCards(player, player.one, GameRule.ONE, winc, isWinnerIsLandlord, winnerCardCount);
				if (!one) {
					if (isWinnerIsLandlord || player.nextPlayer.isLandlord) {
						// 堵门的偏家,大牌上,自己不要想着赢
						for (var i: number = 0; i < player.cardList.length; i++) {
							if (player.cardList[i].val <= 15 && player.cardList[i].val > winc.val) {
								return {
									cardList: player.cardList.slice(i, i + 1),
									cardKind: GameRule.ONE,
									size: 1,
									val: player.cardList[i].val
								}
							}
						}
					}
					if (AILogic.times(player) <= 1 && player.pairs.length > 0 && player.pairs[0].val > 10) {
						// 如果剩下一对,并且大于10,就要拆牌
						var c = player.cardList.slice(0, 1);
						if (c[0].val > winc.val) {
							return {
								cardList: c,
								cardKind: GameRule.ONE,
								size: 1,
								val: c[0].val
							}
						} else {
							return null;
						}
					}
				}
				return one;
			case GameRule.PAIRS:
				var pairs = player.pairs.length > 0 ? AILogic.matchCards(player, player.pairs, GameRule.PAIRS, winc, isWinnerIsLandlord, winnerCardCount) : null;
				// 对子的跟牌
				if (pairs == null && (isWinnerIsLandlord || player.nextPlayer.isLandlord)) {
					// 拆牌顶住地主
					if (player.progressionPairs.length > 0) {
						// 拆连对
						for (var i: number = player.progressionPairs.length - 1; i >= 0; i--) {
							if (winc.val >= player.progressionPairs[i].val) {
								continue;
							}
							for (var j: number = player.progressionPairs[i].cardList[j].length - 1; j >= 0; j -= 2) {
								if (player.progressionPairs[i].cardList[j].val > winc.val) {
									var pairsFromPP = player.progressionPairs[i].cardList.splice(j - 1, 2);
									return {
										cardList: pairsFromPP,
										cardKind: GameRule.PAIRS,
										size: 2,
										val: pairsFromPP[0].val
									}
								}
							}
						}
					} else if (player.three.length > 0) {
						// 拆三根
						for (var i: number = player.three.length - 1; i >= 0; i--) {
							if (player.three[i].val > winc.val) {
								return {
									cardList: player.three[i].cardList.slice(0, 2),
									cardKind: GameRule.PAIRS,
									size: 2,
									val: player.three[i].val
								}
							}
						}
					}
				}
				return pairs;
			case GameRule.THREE:
				if (!isWinnerIsLandlord && !player.isLandlord) {
					return null;
				}
				return AILogic.matchCards(player, player.three, GameRule.THREE, winc, isWinnerIsLandlord, winnerCardCount);
			case GameRule.THREE_WITH_ONE:
				// 三带一
				if (!isWinnerIsLandlord && !player.isLandlord) {
					return null;
				}
				var three = AILogic.minCards(player.three, GameRule.THREE, winc.val);
				if (three) {
					var one = AILogic.minOne(2, three.val, player);
					if (!one) {
						return null;
					} else {
						three.cardList.push(one);
					}
					three.cardKind = GameRule.THREE_WITH_ONE;
					three.size = 4;
				}
				return three;
			case GameRule.THREE_WITH_PAIRS:
				// 三代二	
				if (!isWinnerIsLandlord && !player.nextPlayer.isLandlord) {
					return null;
				}
				var three = AILogic.minCards(player.three, GameRule.THREE, winc.val);
				if (three) {
					var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS);
					while (true) {
						// 避免对子和三根重叠
						if (pairs && pairs.cardList[0].val === three.val) {
							pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, pairs.cardList[0].val);
						} else {
							break;
						}
					}
					if (pairs) {
						three.cardList = three.cardList.concat(pairs.cardList);
					} else {
						return null;
					}
					three.cardKind = GameRule.THREE_WITH_PAIRS;
					three.size = 5;
				}
				return three;
			case GameRule.PROGRESSION:
				// 顺子
				if (!isWinnerIsLandlord && !player.nextPlayer.isLandlord) {
					return null;
				}
				if (player.progression.length > 0) {
					for (var i: number = player.progression.length - 1; i >= 0; i--) {
						if (winc.val < player.progression[i].val && winc.size <= player.progression[i].cardList.length) {
							if (winc.size === player.progression[i].cardList.length) {
								return AILogic.setCardKind(player.progression[i], GameRule.PROGRESSION);
							} else {
								if (player.isLandlord || isWinnerIsLandlord) {
									var valDiff = player.progression[i].val - winc.val;
									var sizeDiff = player.progression[i].cardList.length - winc.size;
									for (var j: number = 0; j < sizeDiff; j++) {
										// 拆顺子
										if (valDiff > 1) {
											player.progression[i].cardList.shift();
											player.progression[i].val--;
											valDiff--;
											continue;
										}
										player.progression[i].cardList.pop();
									}
									return AILogic.setCardKind(player.progression[i], GameRule.PROGRESSION);
								} else {
									return null;
								}
							}
						}
					}
				}
				return null;
			case GameRule.PROGRESSION_PAIRS:
				// 连对
				if (!isWinnerIsLandlord && !player.nextPlayer.isLandlord) {
					return null;
				}
				if (player.progressionPairs.length > 0) {
					for (var i = player.progressionPairs.length - 1; i >= 0; i--) {//从小值开始判断
						if (winc.val < player.progressionPairs[i].val && winc.size <= player.progressionPairs[i].cardList.length) {
							if (winc.size === player.progressionPairs[i].cardList.length) {
								return AILogic.setCardKind(player.progressionPairs[i], GameRule.PROGRESSION_PAIRS);
							} else {
								if (player.isLandlord || isWinnerIsLandlord) {
									var valDiff = player.progressionPairs[i].val - winc.val,
										sizeDiff = (player.progressionPairs[i].cardList.length - winc.size) / 2;
									for (var j = 0; j < sizeDiff; j++) {//拆顺
										if (valDiff > 1) {
											player.progressionPairs[i].cardList.shift();
											player.progressionPairs[i].cardList.shift();
											valDiff--;
											continue;
										}
										player.progressionPairs[i].cardList.pop();
										player.progressionPairs[i].cardList.pop();
									}
									return AILogic.setCardKind(player.progressionPairs[i], GameRule.PROGRESSION_PAIRS);
								} else {
									return null;
								}
							}
						}
					}
				}
				return null;
			case GameRule.PLANE:
				if (!isWinnerIsLandlord && !player.isLandlord) {
					return null;
				}
				return AILogic.minPlane(winc.size, winc, player);
			case GameRule.PLANE_WITH_ONE:
				// 飞机带单
				if (!isWinnerIsLandlord && !player.nextPlayer.isLandlord) {
					return null;
				}
				var cnt = winc.size / 4;
				var plane = AILogic.minPlane(cnt * 3, winc, player);
				if (plane) {
					var currOneVal = 2;
					for (var i: number = 0; i < cnt; i++) {
						var one = AILogic.minOne(currOneVal, plane.val, player);
						if (one) {
							plane.cardList.push(one);
							currOneVal = one.val;
						} else {
							return null;
						}
					}
					plane.cardKind = GameRule.PLANE_WITH_ONE;
					plane.size = plane.cardList.length;
				}
				return plane;
			case GameRule.PLANE_WITH_PAIRS:
				if (!isWinnerIsLandlord && !player.nextPlayer.isLandlord) {
					return null;
				}
				var cnt = winc.size / 5;
				var plane = AILogic.minPlane(cnt * 3, winc, player);
				if (plane) {
					var currOneVal = 2;
					for (var i: number = 0; i < cnt; i++) {
						var pairs = AILogic.minCards(player.pairs, GameRule.PAIRS, currOneVal);
						if (pairs) {
							plane.cardList = plane.cardList.concat(pairs.cardList);
							currOneVal = pairs.val;
						} else {
							return null;
						}
					}
					plane.cardKind = GameRule.PLANE_WITH_PAIRS;
					plane.size = plane.cardList.length;
				}
				return plane;
			case GameRule.BOMB:
				if (!isWinnerIsLandlord && !player.isLandlord) {
					return null;
				}
				var bomb = AILogic.minCards(player.bomb, GameRule.BOMB, winc.val);
				if (bomb) {
					return bomb;
				} else {
					if ((player.kingBomb.length > 0)) {
						if ((isWinnerIsLandlord && winnerCardCount < 6) || (player.isLandlord && player.cardList.length < 6)) {
							return AILogic.setCardKind(player.kingBomb[0], GameRule.KING_BOMB);
						}
					}
					return null;
				}
			case GameRule.FOUR_WITH_TWO:
				return AILogic.minCards(player.bomb, GameRule.BOMB, winc.val);
			case GameRule.FOUR_WITH_TWO_PAIRS:
				return AILogic.minCards(player.bomb, GameRule.BOMB, winc.val);
			case GameRule.KING_BOMB:
				return null;
			default:
				return null;
			// case	
		}
	}
	/**
	 * 根据自己是否是庄家,来决定出牌
	 * list 出牌列表
	 * kind 牌型
	 * winc 当前牌面最大牌
	 * isWinnerIsLandlord 当前最大是否是地主
	 * winnerCardCount 当前最大那家剩余手牌数
	*/
	public static matchCards(player: Player, list, kind, winc, isWinnerIsLandlord, winnerCardCount) {
		if (player.isLandlord) {
			// 坐庄
			if (player.nextPlayer.cardList.length < 3 || player.nextPlayer.nextPlayer.cardList.length < 3) {
				return AILogic.maxCards(list, kind, winc.val);
			} else {
				return AILogic.minCards(list, kind, winc.val);
			}
		} else {
			// 偏家
			if (isWinnerIsLandlord) {
				// 地主大的时候
				if (winnerCardCount < 3) {
					return AILogic.maxCards(list, kind, winc.val);
				} else {
					return AILogic.minCards(list, kind, winc.val);
				}
			} else {
				var c = null;
				if (player.nextPlayer.isLandlord && player.nextPlayer.cardList.length < 3) {
					return AILogic.maxCards(list, kind, winc.val);
				} else {
					c = AILogic.minCards(list, kind, winc.val);
					return c ? (c.val < 14 || AILogic.times(player) <= 2 ? c : null) : null;
				}
			}
		}
	}
	/**
	 * 获取大过当前出牌的三顺最小值
	 * len 指定牌张数
	*/
	public static minPlane(len, winc, player: Player) {
		if (player.plane.length > 0) {
			for (var i: number = player.plane.length - 1; i >= 0; i--) {
				if (winc.val < player.plane[i].val && len <= player.plane[i].cardList.length) {
					if (len === player.plane[i].cardList.length) {
						return AILogic.setCardKind(player.plane[i], GameRule.PLANE);
					} else {
						var valDiff = player.plane[i].val - winc.val;
						var sizeDiff = (player.plane[i].cardList.length - len) / 3;
						for (var j: number = 0; j < sizeDiff; j++) {
							if (valDiff > 1) {
								for (var k: number = 0; k < 3; k++) {
									player.plane[i].cardList.shift();
								}
								valDiff--;
								continue;
							}
							for (var k: number = 0; k < 3; k++) {
								player.plane[i].cardList.pop();
							}
						}
						return AILogic.setCardKind(player.plane[i], GameRule.PLANE);
					}

				}

			}

		}
		return null;
	}
}